<?php
/**
 * Actions modify the AMF message PER BODY
 * This allows batching of calls
 * 
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @copyright (c) 2003 amfphp.org
 * @package flashservices
 * @subpackage filters
 * @version $Id: Filters.php,v 1.6 2005/04/02   18:37:51 pmineault Exp $
 */

/**
 * Catches any special request types and classifies as required
 */
function adapterAction (&$amfbody) {
	$baseClassPath = $GLOBALS['amfphp']['classPath'];
	$uriclasspath = "";
	$classname = "";
	$classpath = "";
	$methodname = "";
	$isWebServiceURI = false;

	$target = $amfbody->targetURI;
	
	if (strpos($target, "http://") === false && strpos($target, "https://") === false) { // check for a http link which means web service
		$lpos = strrpos($target, ".");
		if ($lpos === false) {
			//Check to see if this is in fact a RemotingMessage
			$body = $amfbody->getValue();
			$handled = false;
			
			$messageType = $body[0]->_explicitType;
			if ($messageType == 'flex.messaging.messages.RemotingMessage')
			{
				$handled = true;
				
				//Fix for AMF0 mixed array bug in Flex 2
				if(isset($body[0]->body['length']))
				{
					unset($body[0]->body['length']);
				}
				
				$amfbody->setValue($body[0]->body);
				$amfbody->setSpecialHandling("RemotingMessage");
				$amfbody->setMetadata("clientId", $body[0]->clientId);
				$amfbody->setMetadata("messageId", $body[0]->messageId);
				
				$GLOBALS['amfphp']['lastMessageId'] = $body[0]->messageId;
				
				$methodname = $body[0]->operation;
				$classAndPackage = $body[0]->source;
				$lpos = strrpos($classAndPackage, ".");
				if($lpos !== FALSE)
				{
					$classname = substr($classAndPackage, $lpos + 1);
				}
				else
				{
					$classname = $classAndPackage;
				}
				$uriclasspath = str_replace('.','/',$classAndPackage) . '.php';
				$classpath = $baseClassPath . $uriclasspath;
			}
			elseif($messageType == "flex.messaging.messages.CommandMessage")
			{
				if($body[0]->operation == 5)
				{
					$handled = true;
					$amfbody->setSpecialHandling("Ping");
					$amfbody->setMetadata("clientId", $body[0]->clientId);
					$amfbody->setMetadata("messageId", $body[0]->messageId);
					$amfbody->noExec = true;
				}
			}
			
			if(!$handled)
			{
				$uriclasspath = "amfphp/Amf3Broker.php";
				$classpath = $baseClassPath . "amfphp/Amf3Broker.php";
				$classname = "Amf3Broker";
				$methodname = "handleMessage";
			}
		} else {
			$methodname = substr($target, $lpos + 1);
			$trunced = substr($target, 0, $lpos);
			$lpos = strrpos($trunced, ".");
			if ($lpos === false) {
				$classname = $trunced;
				if ($classname == "PageAbleResult" && $methodname == 'getRecords') {
					$val = $amfbody->getValue();
					$id = $val[0];
					$keys = explode("=", $id);
					$currset = intval($keys[1]);
					
					$set = $_SESSION['amfphp_recordsets'][$currset];
					
					$uriclasspath = $set['class'];
					$classpath = $baseClassPath . $set['class'];
					$methodname = $set['method'];
					
					$classname = substr(strrchr('/' . $set['class'], '/'), 1, -4);
					
					//Now set args for body
					$amfbody->setValue(array_merge($set['args'], array($val[1], $val[2])));
					
					//Tell amfbody that this is a dynamic paged resultset
					$amfbody->setSpecialHandling('pageFetch');
				} 
				else if($classname == "PageAbleResult" && $methodname == 'release')
				{
					$amfbody->setSpecialHandling('pageRelease');
					$amfbody->noExec = true;
				}
				else {
					$uriclasspath = $trunced . ".php";
					$classpath = $baseClassPath . $trunced . ".php";
				} 
			} else {
				$classname = substr($trunced, $lpos + 1);
				$classpath = $baseClassPath . str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here
				$uriclasspath = str_replace(".", "/", $trunced) . ".php"; // removed to strip the basecp out of the equation here
			} 
		}
	} else { // This is a web service and is unsupported
		trigger_error("Web services are not supported in this release", E_USER_ERROR);
	}

	$amfbody->classPath = $classpath;
	$amfbody->uriClassPath = $uriclasspath;
	$amfbody->className = $classname;
	$amfbody->methodName = $methodname;

	return true;
} 

/**
 * ExecutionAction executes the required methods
 */
function executionAction (&$amfbody) 
{
	$specialHandling = $amfbody->getSpecialHandling();

	if (!$amfbody->isSpecialHandling() || $amfbody->isSpecialHandling(array('describeService', 'pageFetch', 'RemotingMessage')))
	{
		$construct = &$amfbody->getClassConstruct();
		$method = $amfbody->methodName;
		$args = $amfbody->getValue();
		
//		if (is_array($args[0])) {
//			$args = $args[0];
//			file_put_contents(
//					'd:/www/mc2.new/tmp/'.$amfbody->className.'-'.$method.'-'.uniqid().'.txt', 
//					var_export($args,true)
//			);
//		}
		
		if($specialHandling == 'describeService')
		{               
			include_once(AMFPHP_BASE . "util/DescribeService.php");
			$ds = new DescribeService();
			$results = $ds->describe($construct, $amfbody->className);
		}
		else if($specialHandling == 'pageFetch')
		{
			echo 333;
			$args[count($args) - 2] = $args[count($args) - 2] - 1;
			
			$dataset = Executive::doMethodCall($amfbody, $construct, $method, $args);
			$results = array("cursor" => $args[count($args) - 2] + 1,
							 "data" => $dataset);
			$amfbody->setMetadata('type', '__DYNAMIC_PAGE__');
		}
		else
		{
			/************************************************************
			 * 修改版 
			 ***********************************************************/
			global $L, $amfphp, $results, $ignoreMethod;
			global $_ERR;
			
			$time = microtime_float();
			$clsMth = $amfbody->className.'::'.$method;
			
//			file_put_contents('d:/www/mc2.new/'.uniqid().'.txt', $clsMth);
			
//			// 客户端传递sessionID到服务器端
//			if (is_string($args[0][0]) && strlen($args[0][0]) > 15) {
//				$sessionid = $args[0][0];
//				$_args = $args[0];
//				array_shift($args[0]);
//			}
			
			// 测试环境获取amf服务方法列表
			if($GLOBALS['debug'] && $amfbody->className=='DiscoveryService')
			{
				$results = Executive::doMethodCall($amfbody, $construct, $method, $args);
				if ($method != 'getServices') {
					$obj_class = $amfbody->_value[0]['label'];
				}
				if (is_array($results[0])) {
					foreach ($results[0] as $k => $v) {
						if (is_array($results[0][$k]['arguments'])) {
							$first_arg = $results[0][$k]['arguments'][0];
							if (isset($args[0]['label']) && 0===strpos($first_arg, 'uid')) { 
								array_shift($results[0][$k]['arguments']);
							}
						}
						
						// 过滤方法列表不发送给客户端
						$meth = $obj_class.'::'.$k;
						if (in_array($k, $ignoreMethod) || in_array($meth, $ignoreMethod)) {
							unset($results[0][$k]);
						}
					}
				} else {
					$results = array(
						'val' => false,
						'msg' => 'method is empty!',
						'class' => $amfbody->className,
						'method' => $method,
						'data' => $results
					);
				}
			}
			//不能被请求的通用方法要被跳过执行
			elseif (in_array($method, $ignoreMethod) || in_array($clsMth, $ignoreMethod)){
				$results = array(
					'val' => false,
					'msg' => 'method is private!',
					'class' => $amfbody->className,
					'method' => $method,
				);
			}
			elseif ($method=='test') {
				$results = Executive::doMethodCall($amfbody, $construct, $method, $args);
			}
			// 用户登录操作
			elseif ($amfbody->className=='SUser' && $method=='login') {
				// 客户端把所有参数当成一个数组传递过来
				if (is_array($args[0])) {
					$args = $args[0];
				}
				$results = Executive::doMethodCall($amfbody, $construct, $method, $args);
				if ($results['val']) {
					$results['logined'] = true;
				} else {
					$results['logined'] = false;
				}
				if (empty($results)) {
					$results = array(
						'val' => false,
						'logined' => false,
						'msg' => 'method no return!',
						'uid' => $_SESSION['uid'],
						'method' => $method,
						'args' => $args,
						'results' => $results
					);
				}
			}
			// 已登录用户的普通操作
			elseif ($_SESSION['uid'] && $_SESSION['created_role']) {
				global $DB, $m;
				$sql = 'SELECT uid,last_login_ip FROM user WHERE uid='.$_SESSION['uid'];
				$user = $DB->getValue($sql);
				// 根据会话ID防止重复登录(限制不同浏览器也不行)
//				if ($_SESSION['sessionid'] != $m->get('sessionid_'.$_SESSION['uid'])) {
//					$results = array(
//						'val'		=> false,
//						'msg'		=> $L['user_is_logined_elsewhere'],
//						'uid'		=> $_SESSION['uid'],
//						'method'	=> $method,
//						'args'		=> $args,
//						'logined'	=> false
//					);
//					// 注销SESSION
//					if (!empty($_SESSION)) {
//						session_destroy();
//					}
//				} else {
					// 客户端把所有参数当成一个数组传递过来
					if (is_array($args[0])) {
						$args = $args[0];
					}
					// 第一个参数固定用户ID,客户端请求时自动设置为$_SESSION['uid']
					array_unshift($args, $_SESSION['uid']);
					// 参数所传用户ID和当前用户的会话中用户ID不一致,非法!
					if (!$GLOBALS['debug'] && $_SESSION['uid'] != $args[0]) {
						$results = array(
							'val'		=> false,
							'msg'		=> $L['Invalid_uid'],
							'uid'		=> $_SESSION['uid'],
							'method'	=> $method,
							'args'		=> $args
						);
					} else {
						// 调用转发的请求
						$results = Executive::doMethodCall($amfbody, $construct, $method, $args);
						if (empty($results)) {
							$results = array(
								'val'		=> false,
								'msg'		=> 'method no return!',
								'uid'		=> $_SESSION['uid'],
								'args'		=> $args,
								'results'	=> $results
							);
						}
					}
					if ($method == 'logout') {
						$results['logined'] = false;
					} else {
						$results['logined'] = true;
					}
//				}
			}
			// 用户还未创建角色
			elseif ($_SESSION['uid'] && !$_SESSION['created_role'] ) {
				// 客户端把所有参数当成一个数组传递过来
				if (is_array($args[0])) {
					$args = $args[0];
				}
				// 如果调用创建角色接口
				if ($amfbody->className=='SUser' && (in_array($method, array('isCreatedRole', 'createRole')))) {
					// 调用转发的请求
					$results = Executive::doMethodCall($amfbody, $construct, $method, $args);
					if (empty($results)) {
						$results = array(
							'val' => false,
							'msg' => 'method no return!'.$clsMth."\n",
							'uid' => $_SESSION['uid'],
							'method'  => $method,
							'args'    => $args,
							'results' => $results
						);
					}
					$results['logined'] = true;
				} else {// 调用其他接口,提示未创建角色
					global $L;
					$results = array(
						'val' => false,
						'logined' => true,
						'msg' => $L['not_create_role'],
						'class' => $amfbody->className,
						'method' => $amfbody->methodName,
						'args' => $args
					);
				}
			}
			// 非法用户请求
			else {
				global $L;
				$results = array(
					'val' => false,
					'logined' => false,
					'msg' => $_SESSION['uid'] ? $L['not_create_role'] : $L['not_login'],
					'class' => $amfbody->className,
					'method' => $amfbody->methodName,
					'args' => $args
				);
			}
			/* 调试:有信息提示,顺便传回客户端请求参数 */
			if (is_string($results)) {
				$results = array(
					'val' => false,
					'logined' => (bool)$_SESSION['uid'],
					'msg' => 'method return error!'.$clsMth."\n"
								.var_export($args, true)."\n\n".
								var_export($_ERR,true),
//					'method'  => $method,
//					'args'    => $args,
					'results' => $results
				);
			} elseif (isset($args) && is_array($results) && isset($results['msg'])) {
				$results['msg'] .= $clsMth."\n".var_export($args, true);
			} elseif (empty($results['val'])) {
				$results['error'] = $clsMth."\n".var_export($args, true);
			}
			if (!$results['logined']) {
				$results['login_url'] = $GLOBALS['loginUrl'];
			}
			$amfphp['callTime'] += microtime_float() - $time;
			$results['srv_time'] = time();
//			$results['session'] = var_export($_SESSION,true);
//			$results['cookie'] = var_export($_COOKIE,true);
//			$results['included_files'] = get_included_files();
			/***********************************************************
			 * end 修改版
			 ***********************************************************/
		}

		if($results !== '__amfphp_error')
		{
			if($specialHandling == 'RemotingMessage')
			{
				
				$wrapper = new AcknowledgeMessage($amfbody->getMetadata("messageId"), 
												  $amfbody->getMetadata("clientId"));
				$wrapper->body = $results;
				$amfbody->setResults($wrapper);
			}
			else
			{
				$amfbody->setResults($results);
			}
			
			$amfbody->responseURI = $amfbody->responseIndex . "/onResult";
		}
		return false;
	}
	elseif($specialHandling == 'Ping')
	{
		$wrapper = new AcknowledgeMessage($amfbody->getMetadata("messageId"), 
										  $amfbody->getMetadata("clientId"));
		$amfbody->setResults($wrapper);
		$amfbody->responseURI = $amfbody->responseIndex . "/onResult";
	}
	else if($specialHandling == 'pageRelease')
	{
		//Ignore PageAbleResult.release
		$amfbody->setResults(true);
		$amfbody->setMetaData('type', 'boolean');
		$amfbody->responseURI = $amfbody->responseIndex . "/onResult";
		return false;
	}
	return true;
}
?>